package com.richinfo.util;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.config.RequestConfig.Builder;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class HttpUtils {
	protected static Log log = LogFactory.getLog("http");
	protected static final Charset charset = Consts.UTF_8;

	protected static CloseableHttpClient client = null;

	static {
		client = initDefualtClient();
	}

	public static String get(String url) throws IOException {
		return get(url, null);
	}

	public static String get(String url, Map<String, Object> param) throws IOException {
		if (MapUtils.isNotEmpty(param)) {
			StringBuilder paramStr = new StringBuilder("?");

			for (Entry<String, Object> entry : param.entrySet()) {
				paramStr.append(entry.getKey());
				paramStr.append("=");
				paramStr.append(URLEncoder.encode(entry.getValue().toString(), "UTF-8"));
				paramStr.append("&");
			}

			paramStr.deleteCharAt(paramStr.length() - 1);

			url = url + paramStr.toString();
		}

		return get(url, charset, null, null);
	}

	public static String postForm(String url, Map<String, Object> params) throws IOException {
		return postForm(url, null, params);
	}

	public static String postForm(String url, Map<String, String> customHeader, Map<String, Object> formParam)
			throws IOException {
		return postForm(url, customHeader, formParam, null, null);
	}

	public static String postForm(String url, Map<String, String> customHeader, Map<String, Object> formParam,
			Integer connTimeout, Integer readTimeout) throws IOException {
		List<NameValuePair> params = new ArrayList<NameValuePair>();
		for (Entry<String, Object> entry : formParam.entrySet()) {
			params.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
		}

		return postForm(url, customHeader, URLEncodedUtils.format(params, charset), connTimeout, readTimeout);
	}

	public static String postForm(String url, Map<String, String> customHeader, String formParam, Integer connTimeout,
			Integer readTimeout) throws IOException {
		return post(url, customHeader, formParam, ContentType.APPLICATION_FORM_URLENCODED, connTimeout, readTimeout);
	}

	public static String postJson(String url, Object jsonParam) throws IOException {
		return postJson(url, null, JsonUtils.write(jsonParam));
	}

	public static String postJson(String url, Map<String, String> customHeader, Object jsonParam) throws IOException {
		return post(url, customHeader, JsonUtils.write(jsonParam), ContentType.APPLICATION_JSON);
	}

	public static String post(String url, String json) throws IOException {
		return post(url, json, ContentType.APPLICATION_JSON);
	}

	public static String post(String url, String body, ContentType contentType) throws IOException {
		return post(url, null, body, contentType);
	}

	public static String post(String url, Map<String, String> customHeader, String body, ContentType contentType)
			throws IOException {
		return post(url, customHeader, body, contentType, null, null);
	}

	public static String post(String url, Map<String, String> customHeader, String body, ContentType contentType,
			Integer connTimeout, Integer readTimeout) throws IOException {
		log.info("http post: url-" + url + " | contentType" + contentType.toString() + " | header-" + customHeader
				+ " | param-" + body);

		HttpPost post = new HttpPost(url);
		CloseableHttpResponse response = null;
		String result = null;

		try {
			if (customHeader != null) {
				for (Entry<String, String> header : customHeader.entrySet()) {
					post.addHeader(header.getKey(), header.getValue());
				}
			}
			if (StringUtils.isNotBlank(body)) {
				HttpEntity entity = new StringEntity(body, contentType);
				post.setEntity(entity);
			}

			// 设置参数
			Builder customReqConfig = RequestConfig.custom();
			if (connTimeout != null) {
				customReqConfig.setConnectTimeout(connTimeout);
			}
			if (readTimeout != null) {
				customReqConfig.setSocketTimeout(readTimeout);
			}
			post.setConfig(customReqConfig.build());

			response = client.execute(post);

			result = EntityUtils.toString(response.getEntity(), charset);

			log.info("http post: url-" + url + " | response-\r\n" + result);
		} finally {
			if (response != null) {
				EntityUtils.consume(response.getEntity());

				response.close();
			}
		}

		return result;
	}

	public static String get(String url, Charset charset, Integer connTimeout, Integer readTimeout) throws IOException {
		log.info("http get: url-" + url);

		HttpGet get = new HttpGet(url);
		CloseableHttpResponse response = null;
		String result = null;

		try {
			Builder customReqConfig = RequestConfig.custom();
			if (connTimeout != null) {
				customReqConfig.setConnectTimeout(connTimeout);
			}
			if (readTimeout != null) {
				customReqConfig.setSocketTimeout(readTimeout);
			}
			get.setConfig(customReqConfig.build());

			response = client.execute(get);

			result = EntityUtils.toString(response.getEntity(), charset);

			log.info("http get: url-" + url + " | response-\r\n" + result);
		} finally {
			if (response != null) {
				EntityUtils.consume(response.getEntity());

				response.close();
			}
		}

		return result;
	}

	public static CloseableHttpClient initDefualtClient() {
		try {
			SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
				@Override
				public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
					return true;
				}
			}).build();

			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new X509HostnameVerifier() {

				@Override
				public boolean verify(String arg0, SSLSession arg1) {
					return true;
				}

				@Override
				public void verify(String host, SSLSocket ssl) throws IOException {
				}

				@Override
				public void verify(String host, X509Certificate cert) throws SSLException {
				}

				@Override
				public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
				}

			});

			return HttpClients.custom().setSSLSocketFactory(sslsf).build();

		} catch (GeneralSecurityException e) {
			throw new RuntimeException(e);
		}
	}

	public static void main(String[] args) {
		try {
			HttpUtils.get("http://www.baidu.com");

			HttpUtils.post("https://imoa.gmcc.net:8081/gmccservice/v5/codeLogin",
					"{\"encrypt\": \"REm0WAO3q0AE3vvHY9XRbuPAVM7KnzYaVYkfGuvm1tMwnyTqogHnNPRhU+YTs/LesG7aT0DJiYUPHG3XAWhJHtsZMCkEXE2tWoDTK5TGeEKS+4Aak1Rd/NxULwjboB8f5tEWHhDvlaXpAaPq4stX8FdlKNKYFaWgbWs90p1OZCWcKQW/4DUcTxS91kHYrHlWvvXd2l7mOnip/pLtA/Z3FK9zQxwKzJeaGmknOX0ZzO0Sd1owwjF026SJIQVEgoUCXBUiSl0frWpepH6WVmfk2K5FknIFspfLKNqEUc7UXhmesPS7XEXITZur0NkZKjpc\"}");
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

}
